import json
import time
import ctypes
from ctypes import wintypes
import argparse
from datetime import datetime

# Windows API函数
user32 = ctypes.windll.user32

# 输入事件结构
class INPUT(ctypes.Structure):
    class _INPUT(ctypes.Union):
        class _ki(ctypes.Structure):
            _fields_ = [("wVk", wintypes.WORD),
                       ("wScan", wintypes.WORD),
                       ("dwFlags", wintypes.DWORD),
                       ("time", wintypes.DWORD),
                       ("dwExtraInfo", ctypes.POINTER(wintypes.ULONG))]
        
        class _mi(ctypes.Structure):
            _fields_ = [("dx", wintypes.LONG),
                       ("dy", wintypes.LONG),
                       ("mouseData", wintypes.DWORD),
                       ("dwFlags", wintypes.DWORD),
                       ("time", wintypes.DWORD),
                       ("dwExtraInfo", ctypes.POINTER(wintypes.ULONG))]
        
        _fields_ = [("ki", _ki), ("mi", _mi)]
    
    _fields_ = [("type", wintypes.DWORD), ("data", _INPUT)]

# 常量
INPUT_MOUSE = 0
INPUT_KEYBOARD = 1
KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP = 0x0002
MOUSEEVENTF_MOVE = 0x0001
MOUSEEVENTF_LEFTDOWN = 0x0002
MOUSEEVENTF_LEFTUP = 0x0004
MOUSEEVENTF_RIGHTDOWN = 0x0008
MOUSEEVENTF_RIGHTUP = 0x0010
MOUSEEVENTF_MIDDLEDOWN = 0x0020
MOUSEEVENTF_MIDDLEUP = 0x0040
MOUSEEVENTF_ABSOLUTE = 0x8000

class EventReplayer:
    """事件回放器"""
    
    def __init__(self):
        self.events = []
        self.start_time = None
        
    def load_events(self, file_path: str) -> bool:
        """加载事件文件"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            self.events = data.get('events', [])
            recording_info = data.get('recording_info', {})
            
            print(f"📂 加载事件文件: {file_path}")
            print(f"📊 事件统计:")
            if 'statistics' in data:
                stats = data['statistics']
                print(f"  - 总事件数: {stats.get('total_events', 0)}")
                print(f"  - 键盘事件: {stats.get('keyboard_events', 0)}")
                print(f"  - 鼠标事件: {stats.get('mouse_events', 0)}")
                print(f"  - 按键次数: {stats.get('key_press_count', 0)}")
                print(f"  - 点击次数: {stats.get('mouse_click_count', 0)}")
            
            print(f"⏱️ 录制时长: {recording_info.get('total_duration', 0):.2f}秒")
            print(f"🕐 录制时间: {recording_info.get('recorded_at', 'Unknown')}")
            
            # 显示窗口信息
            window_info = recording_info.get('window_info', {})
            if window_info:
                print(f"🪟 目标窗口: {window_info.get('title', 'Unknown')}")
                if window_info.get('hwnd'):
                    print(f"🔗 窗口句柄: {window_info.get('hwnd')}")
            
            return True
            
        except Exception as e:
            print(f"❌ 加载事件文件失败: {e}")
            return False
    
    def replay_events(self, speed_multiplier: float = 1.0, dry_run: bool = False):
        """回放事件"""
        if not self.events:
            print("❌ 没有可回放的事件")
            return
        
        print(f"🎬 开始回放事件，速度倍率: {speed_multiplier}x")
        if dry_run:
            print("🔍 预览模式（不会实际执行按键）")
        else:
            print("⚠️  实际回放模式，将在3秒后开始...")
            for i in range(3, 0, -1):
                print(f"倒计时: {i}")
                time.sleep(1)
        
        start_time = time.time()
        
        for i, event in enumerate(self.events):
            # 计算等待时间
            target_time = event['timestamp'] / speed_multiplier
            current_time = time.time() - start_time
            wait_time = target_time - current_time
            
            if wait_time > 0:
                time.sleep(wait_time)
            
            # 执行事件
            if not dry_run:
                self._execute_event(event)
            else:
                self._preview_event(event, i)
        
        print(f"✅ 回放完成，共执行 {len(self.events)} 个事件")
    
    def _execute_event(self, event):
        """执行单个事件"""
        try:
            if event['type'] == 'keyboard':
                self._execute_keyboard_event(event)
            elif event['type'] == 'mouse':
                self._execute_mouse_event(event)
        except Exception as e:
            print(f"❌ 执行事件失败: {e}")
    
    def _execute_keyboard_event(self, event):
        """执行键盘事件"""
        vk_code = event.get('key_code', 0)
        is_keyup = event['action'] == 'up'
        
        # 创建键盘输入结构
        kbd_input = INPUT()
        kbd_input.type = INPUT_KEYBOARD
        kbd_input.data.ki.wVk = vk_code
        kbd_input.data.ki.wScan = 0
        kbd_input.data.ki.dwFlags = KEYEVENTF_KEYUP if is_keyup else 0
        kbd_input.data.ki.time = 0
        kbd_input.data.ki.dwExtraInfo = None
        
        # 发送输入
        result = user32.SendInput(1, ctypes.byref(kbd_input), ctypes.sizeof(INPUT))
        if result != 1:
            print(f"⚠️ 键盘事件发送失败: {event['key_name']} {event['action']}")
        else:
            print(f"⌨️ {event['key_name']} {event['action']}")
    
    def _execute_mouse_event(self, event):
        """执行鼠标事件"""
        action = event['action']
        x = event['x']
        y = event['y']
        
        # 创建鼠标输入结构
        mouse_input = INPUT()
        mouse_input.type = INPUT_MOUSE
        mouse_input.data.mi.dx = x
        mouse_input.data.mi.dy = y
        mouse_input.data.mi.mouseData = 0
        mouse_input.data.mi.time = 0
        mouse_input.data.mi.dwExtraInfo = None
        
        # 设置标志
        if action == 'move':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE
            # 转换为绝对坐标
            screen_width = user32.GetSystemMetrics(0)
            screen_height = user32.GetSystemMetrics(1)
            mouse_input.data.mi.dx = int(x * 65535 / screen_width)
            mouse_input.data.mi.dy = int(y * 65535 / screen_height)
        elif action == 'left_down':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_LEFTDOWN
        elif action == 'left_up':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_LEFTUP
        elif action == 'right_down':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN
        elif action == 'right_up':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_RIGHTUP
        elif action == 'middle_down':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN
        elif action == 'middle_up':
            mouse_input.data.mi.dwFlags = MOUSEEVENTF_MIDDLEUP
        else:
            return  # 未知动作
        
        # 发送输入
        result = user32.SendInput(1, ctypes.byref(mouse_input), ctypes.sizeof(INPUT))
        if result != 1:
            print(f"⚠️ 鼠标事件发送失败: {action} at ({x}, {y})")
        else:
            if action != 'move':  # 不显示移动事件，太多了
                print(f"🖱️ {action} at ({x}, {y})")
    
    def _preview_event(self, event, index):
        """预览事件（不实际执行）"""
        timestamp = event['timestamp']
        event_type = event['type']
        
        if event_type == 'keyboard':
            key_name = event['key_name']
            action = event['action']
            print(f"[{index:04d}] {timestamp:6.2f}s - ⌨️ {key_name} {action}")
        elif event_type == 'mouse':
            action = event['action']
            x = event['x']
            y = event['y']
            if action != 'move':  # 不显示移动事件
                print(f"[{index:04d}] {timestamp:6.2f}s - 🖱️ {action} at ({x}, {y})")
    
    def analyze_events(self):
        """分析事件"""
        if not self.events:
            print("❌ 没有事件可分析")
            return
        
        print("📈 事件分析报告:")
        
        # 按类型统计
        keyboard_events = [e for e in self.events if e['type'] == 'keyboard']
        mouse_events = [e for e in self.events if e['type'] == 'mouse']
        
        print(f"📊 事件统计:")
        print(f"  - 键盘事件: {len(keyboard_events)}")
        print(f"  - 鼠标事件: {len(mouse_events)}")
        
        # 按键频率统计
        key_count = {}
        for event in keyboard_events:
            if event['action'] == 'down':  # 只统计按下
                key = event['key_name']
                key_count[key] = key_count.get(key, 0) + 1
        
        if key_count:
            print(f"🎹 按键频率 (前10):")
            sorted_keys = sorted(key_count.items(), key=lambda x: x[1], reverse=True)
            for key, count in sorted_keys[:10]:
                print(f"  - {key}: {count} 次")
        
        # 鼠标点击统计
        click_count = {}
        for event in mouse_events:
            if 'down' in event['action']:
                button = event['action'].replace('_down', '')
                click_count[button] = click_count.get(button, 0) + 1
        
        if click_count:
            print(f"🖱️ 鼠标点击:")
            for button, count in click_count.items():
                print(f"  - {button}: {count} 次")

def main():
    parser = argparse.ArgumentParser(description="按键事件回放器")
    parser.add_argument("file", help="事件文件路径 (JSON格式)")
    parser.add_argument("--speed", type=float, default=1.0, help="回放速度倍率 (默认: 1.0)")
    parser.add_argument("--preview", action="store_true", help="预览模式，不实际执行")
    parser.add_argument("--analyze", action="store_true", help="只分析事件，不回放")
    
    args = parser.parse_args()
    
    replayer = EventReplayer()
    
    if not replayer.load_events(args.file):
        return
    
    if args.analyze:
        replayer.analyze_events()
    else:
        replayer.replay_events(args.speed, args.preview)

if __name__ == "__main__":
    main()
